
#include <iostream>
#include "EOFCapture.h"

using namespace std;


EOFCapture::EOFCapture(int usePredefineId)
{
	switch (usePredefineId) {
	case 0:
		width = 640;
		height = 480;

		KinectDepthColorWrapper *mKdcCapture = new KinectDepthColorWrapper;
		mKdcCapture->init(width, height);

		mDeviceTypes.push_back(DEVICE_TYPE_KINECT_DEPTH_COLOR);
		mDevicePtrs.push_back(mKdcCapture);
		mCreateByMe.push_back(true);

		VideoCapture *capture = new VideoCapture(CV_CAP_DSHOW+1);
		capture->set(CV_CAP_PROP_FRAME_WIDTH, width);
		capture->set(CV_CAP_PROP_FRAME_HEIGHT, height);

		mDeviceTypes.push_back(DEVICE_TYPE_OPENCV_COLOR);
		mDevicePtrs.push_back(capture);
		mCreateByMe.push_back(true);
		break;
	}

	grayRes = NULL;
	depthRes = NULL;
	colorRes = NULL;
	mappedRes = NULL;

}


EOFCapture::~EOFCapture(void)
{
	for (int i=0; i<mDevicePtrs.size(); ++i) {
		if (mCreateByMe[i]) {
			switch (mDeviceTypes[i]) {
			case DEVICE_TYPE_KINECT_DEPTH:
				delete (KinectDepthWrapper*)mDevicePtrs[i];
				break;
			case DEVICE_TYPE_KINECT_DEPTH_COLOR:
				delete (KinectDepthColorWrapper*)mDevicePtrs[i];
				break;
			case DEVICE_TYPE_OPENCV_COLOR:
				delete (VideoCapture*)mDevicePtrs[i];
				break;
			default:
				cout << "unknown device!!!" << endl;
			}
		}
	}

	if (grayRes != NULL) {
		cvReleaseMat(&grayRes);
	}
	if (depthRes != NULL) {
		cvReleaseMat(&depthRes);
	}
	if (colorRes != NULL) {
		cvReleaseMat(&colorRes);
	}
	if (mappedRes != NULL) {
		cvReleaseMat(&mappedRes);
	}

}


bool EOFCapture::Retrieve( int id /*= -1*/ )
{
	Mat depth, color, mapped, gray;
	bool res = true;

	if (id == -1) {
		mFrames.clear();
		for (int i=0; i<mDevicePtrs.size(); ++i) {
			switch (mDeviceTypes[i]) {
			case DEVICE_TYPE_KINECT_DEPTH_COLOR:
				res &= ((KinectDepthColorWrapper*)mDevicePtrs[i])->retrieve(depthRes, colorRes, mappedRes);

				color = Mat(colorRes);
				mFrames.push_back(color);
				mFrameMeta.push_back(FrameMeta(DEVICE_TYPE_KINECT_COLOR, i));

				mapped = Mat(mappedRes);
				mFrames.push_back(mapped);
				mFrameMeta.push_back(FrameMeta(DEVICE_TYPE_KINECT_DEPTH, i));
				break;
			case DEVICE_TYPE_OPENCV_COLOR:
				res &= ((VideoCapture*)mDevicePtrs[i])->read(gray);
				flip(gray, gray, 1);

				mFrames.push_back(gray);
				mFrameMeta.push_back(FrameMeta(DEVICE_TYPE_OPENCV_COLOR, i));
				break;
			case DEVICE_TYPE_FILE_COLOR:
				{
				ColorReader *reader;
				reader = (ColorReader *) mDevicePtrs[i];
				if (colorRes == NULL)
					colorRes = cvCreateMat(reader->height, reader->width, CV_8UC3);
				res &= reader->getNextFrame(colorRes->data.ptr);

				color = Mat(colorRes);
				mFrames.push_back(color);
				mFrameMeta.push_back(FrameMeta(DEVICE_TYPE_FILE_COLOR, i));
				break;
				}
			case DEVICE_TYPE_FILE_DEPTH:
				{
				DepthReader *reader;
				reader = (DepthReader *) mDevicePtrs[i];
				if (mappedRes == NULL)
					mappedRes = cvCreateMat(reader->height, reader->width, CV_16S);
				res &= reader->getNextFrame(mappedRes->data.s);

				mapped = Mat(mappedRes);
				mFrames.push_back(mapped);
				mFrameMeta.push_back(FrameMeta(DEVICE_TYPE_FILE_DEPTH, i));
				break;
				}
			case DEVICE_TYPE_FILE_GRAY:
				{
				GrayReader *reader;
				reader = (GrayReader *) mDevicePtrs[i];
				if (grayRes == NULL)
					grayRes = cvCreateMat(reader->height, reader->width, CV_8U);
				res &= reader->getNextFrame(grayRes->data.ptr);

				gray = Mat(grayRes);
				mFrames.push_back(gray);
				mFrameMeta.push_back(FrameMeta(DEVICE_TYPE_FILE_GRAY, i));
				break;
				}
			default:
				cout << "unknown device!" << endl;
			}
		}
	}

	return res;

}

int EOFCapture::SetCapture( VideoCapture *cap )
{
	mDeviceTypes.push_back(DEVICE_TYPE_OPENCV_COLOR);
	mDevicePtrs.push_back(cap);
	mCreateByMe.push_back(false);
	return mDevicePtrs.size() - 1;
}

int EOFCapture::SetCapture( KinectDepthColorWrapper *cap )
{
	mDeviceTypes.push_back(DEVICE_TYPE_KINECT_DEPTH_COLOR);
	mDevicePtrs.push_back(cap);
	mCreateByMe.push_back(false);
	return mDevicePtrs.size() - 1;
}

int EOFCapture::SetCapture( KinectDepthWrapper *cap )
{
	mDeviceTypes.push_back(DEVICE_TYPE_KINECT_DEPTH);
	mDevicePtrs.push_back(cap);
	mCreateByMe.push_back(false);
	return mDevicePtrs.size() - 1;
}

int EOFCapture::SetCapture( void *cap, EOFCAPTURE_DEVICE_TYPE type )
{
	mDeviceTypes.push_back(type);
	mDevicePtrs.push_back(cap);
	mCreateByMe.push_back(false);
	return mDevicePtrs.size() - 1;
}

bool EOFCapture::SelectFrame( EOFCAPTURE_DEVICE_TYPE type, Mat& img )
{
	for (int i=0; i<mFrames.size(); ++i) {
		if (mFrameMeta[i].type == type) {
			img = mFrames[i];
			return true;
		}
	}
	return false;
}

bool EOFCapture::SelectFrame( int deviceId, Mat& img )
{
	for (int i=0; i<mFrames.size(); ++i) {
		if (mFrameMeta[i].fromDeviceId == deviceId) {
			img = mFrames[i];
			return true;
		}
	}
	return false;

}

